<!DOCTYPE html>
<html lang="zn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>作用域</title>
    <script>
        /*
            作用域
                -作用域指一个变量的作用的范围
                -在JS中一共有两种作用域:
                    1.全局作用域
                        -直接编写在script标签中的JS代码，都在全局作用域
                        -全局作用域在页面打开时创建，在页面关闭时销毁
                        -在全局作用域中有一个全局对象window
                            它代表的是一个浏览器的窗口，它由浏览器创建我们可以直接使用
                        -在全局作用域中：
                            创建的变量都会作为window对象的属性保存
                            创建的函数都会作为window对象的方法保存
                        -全局作用域中的变量都是全局变量，在页面的任意的部分都可以访问的到
                    
                    2.函数作用域
                        -调用函数时创建函数作用域，函数执行完毕以后，函数作用域销毁
                        -每调用一次函数就会创建一个新的函数作用域，他们之间是相互独立的
                        -在函数作用域中可以访问到全局作用域的变量
                            在全局作用域中无法访问到函数作用域的变量
                        -当在函数作用域操作一个变量时，它会先在自身作用域中寻找，如果有就直接使用
                            如果没有则向上一级作用域中寻找，直至找到全局作用域，
                            如果全局作用域中依然没有找到，则会报错ReferenceError
                        -在函数中要访问全局变量可以使用window对象
        */
        // var a = 10;
        // var b = 20;
        // var c = "hello";

        // console.log(c);
        // console.log(window.c);

        // function fun(){
        //     console.log("我是fun函数");
        // }
        // window.fun();
        // window.alert("hello");

        /*
            变量的声明提前
                使用var关键字声明的变量，会在所有的代码执行之前被声明(但是不会赋值)
                    但是如果声明变量时不使用var关键字,则变量不会被声明提前
            
            函数的提前声明
                使用函数声明形式创建的函数function函数(){}
                    它会在所有的代码执行之前就被创建，所以我们可以在函数声明前来调用函数
                使用函数表达式创建的函数，不会被声明提前，所以不能在声明前调用
        */
        // console.log("a="+a);
        // var a = 123;

        // fun()
        // // 函数声明，会被提前创建
        // function fun(){
        //     console.log("我是一个fun函数");
        // }

        // // fun2();
        // // 函数表达式，不会被提前创建
        // var fun2 = function() {
        //     console.log("我是fun2函数");
        // };

        // fun2();

        var a = 10;

        function fun(){
            var a = "我是fun函数中的变量a";
            var b = 20;

            console.log("a="+a);

            function fun2(){
                console.log("a="+window.a);
            }

            fun2();
        }

        fun();

        /*
            在函数作用域也有声明提前的特性，
                使用var关键字声明的变量，会在函数中所有的代码执行之前被声明
                函数声明也会在函数中所有的代码执行之前执行
        */

        function fun3(){
            fun4();
            console.log(a);
            var a = 35;

            function fun4(){
                alert("I'm fun4");
            }
        }
        fun3();

        var c = 33;
        /*
        在函数中，不适用var声明的变量都会成为全局变量
        */
        function fun5(){
            console.log("c="+c);
            c = 10;

            // d没有使用var关键字，则会设置为全局变量
            d = 100;
        }
        fun5();
    </script>
</head>
<body>
    
</body>
</html>